package com.pine.app.module.security.feign;

import com.pine.app.module.security.core.Authentication;
import com.pine.app.module.security.oauth.config.EnableOAuth2SSOCondition;
import com.pine.app.module.security.oauth.config.properties.OAuth2SsoProperties;
import com.pine.app.module.security.oauth.provider.authentication.BearerTokenExtractor;
import com.pine.app.module.security.oauth.provider.authentication.TokenExtractor;
import com.pine.app.module.security.oauth.provider.sso.token.ClientCredentialsSsoTokenHandler;
import com.pine.app.module.security.oauth.provider.sso.token.OAuth2SsoTokenHandler;
import com.pine.app.module.security.oauth.provider.token.OAuth2AccessToken;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


/**
 * @author xiaoyuan
 * @create 2020/3/25 23:36
 **/
@Configuration
@Slf4j
@Conditional(EnableOAuth2SSOCondition.class)
@ConditionalOnProperty(prefix = "pine.feign.oauth", name = "enabled", havingValue = "true", matchIfMissing = false)
public class FeignAuthSsoRequestInterceptor implements RequestInterceptor {
    public static final String BEARER = "Bearer";
    public static final String AUTHORIZATION = "Authorization";

    private OAuth2SsoTokenHandler oAuth2SsoTokenHandler;
    @Autowired
    private OAuth2SsoProperties clientOauth2Properties;

    private TokenExtractor tokenExtractor = new BearerTokenExtractor();


    @Override
    public void apply(RequestTemplate requestTemplate) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        HttpServletResponse response = attributes.getResponse();
        //未登录检查是否带有token
        Authentication authentication = this.tokenExtractor.extract(request);
        if (authentication != null) {
            //添加token
            requestTemplate.header(AUTHORIZATION, String.format("%s %s", new Object[]{BEARER, authentication.getPrincipal()}));
            return;
        }
        //没有就去授权服务器获取token
        try {
            oAuth2SsoTokenHandler = new ClientCredentialsSsoTokenHandler(clientOauth2Properties);
            OAuth2AccessToken oAuth2AccessToken = oAuth2SsoTokenHandler.getAccessToken(request, response);
            //添加token
            requestTemplate.header(AUTHORIZATION, String.format("%s %s", new Object[]{BEARER, oAuth2AccessToken.getAccessToken()}));
        } catch (IOException e) {
          log.error("feign添加token出现错误，原因：{}",e.getMessage(),e);
        }

    }

}
